package kom;

import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.image.*;
import java.io.IOException;
import javax.swing.JFrame;
import kom.gfx.Screen;
import kom.level.*;

public class Kom extends Canvas implements Runnable {

    private static final long serialVersionUID = 1L;
    private static final String title = "Knights of Monarchy";
    public static final int width = 512, height = 320, scale = 2;
    public static final int TICKS_PER_SECOND = 30;
    public InputHandler input;
    private boolean running;
    private VolatileImage image;
    private Thread thread;
    private int tickCount;
    public static Screen screen;
    private Graphics2D g;

    public void start() {
        running = true;
        thread = new Thread(this);
        thread.start();
    }

    public void stop() {
        running = false;
    }

    private void init() {
        try {
            screen = new Screen(new Bitmaps());
        } catch (IOException e) {
            e.printStackTrace(System.out);
        }
        
        Level level = new Level(20);
        Console.setLevel(level);
        input = new InputHandler(this, level);
        level.setInput(input);
        
        Console.windows.loadWindows();
        Console.windows.activateWindow("quickbar");
    }

    @Override
    public void run() {
        init();
        long lastTime = System.nanoTime();
        double unprocessed = 0;
        double nsPerTick = 1000000000.0 / TICKS_PER_SECOND;
        int frames = 0;
        int ticks = 0;
        long lastTimer1 = System.currentTimeMillis();

        while (running) {
            long now = System.nanoTime();
            unprocessed += (now - lastTime) / nsPerTick;
            lastTime = now;

            while (unprocessed >= 1) {
                ticks++;
                tick();
                unprocessed -= 1;
            }

            frames++;
            render();

            if (System.currentTimeMillis() - lastTimer1 > 1000) {
                lastTimer1 += 1000;
                System.out.println(ticks + " ticks, " + frames + " fps");
                frames = 0;
                ticks = 0;
            }
        }
        System.exit(0);
    }

    private void tick() {
        tickCount++;
        Console.getLevel().tick();
        Console.timer.tick();
    }

    private void render() {
        BufferStrategy bs = getBufferStrategy();
        if (bs == null) {
            requestFocus();
            createBufferStrategy(2);
            bs = getBufferStrategy();
        }

        if (image == null) {
            image = createVolatileImage(width, height);
        }

        if (bs != null) {
            g = image.createGraphics();
            screen.setGraphics(g);

            renderGame(screen);
            g.dispose();

            Graphics gg = bs.getDrawGraphics();
            gg.drawImage(image, 0, 0, width * scale, height * scale, 0, 0, width, height, null);
            gg.dispose();
            bs.show();
        }
    }

    private void renderGame(Screen screen) {
        screen.drawRect(0, 0, width, height, true, screen.getColor(0x4379B7));

        Console.getLevel().render(screen);
        
        screen.setFont("Sans-Serif", Font.PLAIN, 10);
        Rectangle selectedTile = Console.getLevel().getMap().getBoxFromTile(getTileInPixels(input.xMouse, input.yMouse));
        screen.drawRect(selectedTile.x - screen.getOffsX(), selectedTile.y - screen.getOffsY(), selectedTile.width, selectedTile.height, false, Color.BLACK);

        Console.windows.renderWindows(screen);
    }

    public Point2D getTileInPixels(float x, float y) {
        int xTile = (int) (x / 8) + screen.getOffsX() / 8;
        int yTile = (int) (y / 8) + screen.getOffsY() / 8;
        Point2D pt = new Point2D.Float(xTile, yTile);

        return pt;
    }

    public static void main(String[] args) {
        Kom tower = new Kom();
        tower.setMinimumSize(new Dimension(width * scale, height * scale));
        tower.setMaximumSize(new Dimension(width * scale, height * scale));
        tower.setPreferredSize(new Dimension(width * scale, height * scale));

        JFrame frame = new JFrame(title);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(tower);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        tower.start();
    }
}
